package com.alibaba.shopping_user_service.service;

import com.alibaba.shopping_common.pojo.ShoppingUser;
import com.alibaba.shopping_common.result.BusException;
import com.alibaba.shopping_common.result.CodeEnum;
import com.alibaba.shopping_common.service.ShoppingUserService;
import com.alibaba.shopping_common.utils.Md5Util;
import com.alibaba.shopping_user_service.mapper.ShoppingUserMapper;
import com.alibaba.shopping_user_service.util.JwtUtils;
import com.baomidou.mybatisplus.core.conditions.query.Query;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import static com.alibaba.shopping_common.result.CodeEnum.*;

/**
 * @ClassName ShoppingUserServiceImpl
 * @Description TODO
 * @Author Leo
 * @Date 2024/12/16 19:26
 */
@Transactional
@DubboService
public class ShoppingUserServiceImpl implements ShoppingUserService {

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private ShoppingUserMapper shoppingUserMapper;

    /**
     * 把用户的手机号和验证码存入Redis
     * @param phone
     * @param checkCode
     */
    @Override
    public void saveRegisterCheckCode(String phone, String checkCode) {
        ValueOperations valueOperations = redisTemplate.opsForValue();
        // 有效期为5分钟 存储在Redis中的key为 registerCode+手机号，值为验证码
        valueOperations.set("registerCode"+phone,checkCode,3000, TimeUnit.SECONDS);
    }

    @Override
    public void registerCheckCode(String phone, String checkCode) {
        // 根据手机号从Redis中获取验证码
        ValueOperations valueOperations = redisTemplate.opsForValue();
        String code = (String) valueOperations.get("registerCode" + phone);
        if (StringUtils.hasText(code) || !checkCode.equals(code)){
            // 验证码不存在或者用户输入的验证码与Redis中存储不一致,直接抛出异常
            throw new BusException(REGISTER_CODE_CHECK_FAIL);
        }
    }

    /**
     * 用户注册
     * @param shoppingUser 注册数据
     */
    @Override
    public void register(ShoppingUser shoppingUser) {
        // 判断手机号是否已经被注册
        String phone = shoppingUser.getPhone();
        QueryWrapper<ShoppingUser> wrapper1 = new QueryWrapper<>();
        wrapper1.eq("phone",phone);
        List<ShoppingUser> shoppingUsers1 = shoppingUserMapper.selectList(wrapper1);
        // 该手机号已被注册，直接抛出异常
        if (shoppingUsers1 != null && !shoppingUsers1.isEmpty()){
            System.out.println("手机号已经被注册,"+shoppingUsers1);
            throw new BusException(REGISTER_REPEAT_PHONE_ERROR);
        }
        // 判断用户名是否已经被注册
        String username = shoppingUser.getUsername();
        QueryWrapper<ShoppingUser> wrapper2 = new QueryWrapper<>();
        wrapper2.eq("username",username);
        List<ShoppingUser> shoppingUsers2 = shoppingUserMapper.selectList(wrapper2);
        // 该手机号已被注册，直接抛出异常
        if (shoppingUsers2 != null && !shoppingUsers2.isEmpty()){
            throw new BusException(REGISTER_REPEAT_USERNAME_ERROR);
        }

        // 对密码进行MD5加密
        String password = shoppingUser.getPassword();
        String encode = Md5Util.encode(password);
        shoppingUser.setPassword(encode);

        // 将用户状态置为有效
        shoppingUser.setStatus("Y");
        // 将用户信息，写入数据库
        shoppingUserMapper.insert(shoppingUser);
    }

    @Override
    public String loginPassword(String username, String password) {
        System.out.println("========loginPassword========");
        System.out.println("username"+username);
        System.out.println("password"+password);
        // 参数校验
        if (!StringUtils.hasText(username) || !StringUtils.hasText(password)) {
            throw new BusException(CodeEnum.PARAMETER_IS_NULL);
        }
        // 构造查询条件
        QueryWrapper<ShoppingUser> wrapper = new QueryWrapper<>();
        wrapper.eq("username",username);
        // 执行查询
        ShoppingUser shoppingUser = shoppingUserMapper.selectOne(wrapper);
        // 用户未注册
        if (shoppingUser == null || !StringUtils.hasText(shoppingUser.getPassword())){
            throw new BusException(USER_NOT_REGISTERED);
        }
        // 验证密码
        if (!Md5Util.verify(password, shoppingUser.getPassword())) {
            throw new BusException(CodeEnum.PASSWORD_ERROR);
        }
        String sign = JwtUtils.sign(shoppingUser.getId(), shoppingUser.getUsername());
        System.out.println("sign:"+sign);
        return sign;
    }
    // 根据手机号查询用户是否注册
    @Override
    public void checkUserRegister(String phone) {
        // 构造查询条件
        QueryWrapper<ShoppingUser> wrapper = new QueryWrapper<>();
        wrapper.eq("phone",phone);
        // 执行查询
        ShoppingUser shoppingUser = shoppingUserMapper.selectOne(wrapper);
        if (shoppingUser == null ||
                !StringUtils.hasText(shoppingUser.getUsername())
                || !StringUtils.hasText(shoppingUser.getPassword())){
            throw new BusException(CodeEnum.USER_NOT_REGISTERED);
        }
    }

    /**
     * 保存用户登录的验证码
     * @param phone
     * @param checkCode
     */
    @Override
    public void saveLoginCheckCode(String phone, String checkCode) {
        // 写入Redis中
        ValueOperations valueOperations = redisTemplate.opsForValue();
        valueOperations.set("loginCode_"+phone,checkCode,3000,TimeUnit.SECONDS);
    }

    /**
     * 获取用户的name
     * @param token
     * @return
     */
    @Override
    public String getName(String token) {
        // 拿到令牌中的username
        Map<String, Object> verify = JwtUtils.verify(token);
        String username = (String) verify.get("username");
        System.out.println("拿到令牌中的username:"+username);
        return username;
    }

    /**
     * 获取用户信息
     * @param token
     * @return
     */
    @Override
    public ShoppingUser getLoginUser(String token) {
        // 拿到令牌中的ID
        Map<String, Object> verify = JwtUtils.verify(token);
        Long userId = (Long) verify.get("userId");
        // 根据ID查询用户
        QueryWrapper<ShoppingUser> wrapper = new QueryWrapper<>();
        wrapper.eq("id",userId);
        ShoppingUser shoppingUser = shoppingUserMapper.selectOne(wrapper);
        System.out.println("根据ID查询用户:"+shoppingUser);
        return shoppingUser;
    }

    /**
     * 校验用户登录时传入的手机号
     * @param phone
     * @param checkCode
     * @return
     */
    @Override
    public String loginCheckCode(String phone, String checkCode) {
        // 参数校验
        if (!StringUtils.hasText(phone) || !StringUtils.hasText(checkCode)) {
            throw new BusException(CodeEnum.PARAMETER_IS_NULL);
        }
        // 从Redis中获取数据
        ValueOperations operations = redisTemplate.opsForValue();
        String code = (String) operations.get("loginCode_"+phone);
        // 验证码不存在
        if (!StringUtils.hasText(code)){
            throw new BusException(LOGIN_CHECK_NOT_EXIST);
        }
        // 比对验证码
        if (!checkCode.equals(code)){
            throw new BusException(LOGIN_CHECK_CODE_ERROR);
        }
        // 验证码正确，根据手机号查询用户信息
        QueryWrapper<ShoppingUser> wrapper = new QueryWrapper<>();
        wrapper.eq("phone",phone);
        ShoppingUser shoppingUser = shoppingUserMapper.selectOne(wrapper);
        String sign = JwtUtils.sign(shoppingUser.getId(), shoppingUser.getUsername());
        System.out.println("sign:"+sign);
        return sign;
    }
}




